﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AmiEmuLib.AmigaMachine.AmigaMemory;
using System.Diagnostics;
using AmiEmuLib.AmigaConfiguration.CoreConfig;

namespace AmiEmuLib.AmigaMachine.AmigaCPU
{
    /// <summary>
    /// Base for all CPUs.
    /// </summary>
    public abstract class CPU680x0
    {
        /// <summary>
        /// Cycle counter.
        /// </summary>
        public ulong CycleCounter;

        /// <summary>
        /// Memory.
        /// </summary>
        public readonly Memory Memory;

        /// <summary>
        /// Amiga machine.
        /// </summary>
        public readonly Machine Machine;

        [DebuggerDisplay("{Hex.UIntToHex(D0)}")]
        public uint D0;

        [DebuggerDisplay("{Hex.UIntToHex(D1)}")]
        public uint D1;

        [DebuggerDisplay("{Hex.UIntToHex(D2)}")]
        public uint D2;

        [DebuggerDisplay("{Hex.UIntToHex(D3)}")]
        public uint D3;

        [DebuggerDisplay("{Hex.UIntToHex(D4)}")]
        public uint D4;

        [DebuggerDisplay("{Hex.UIntToHex(D5)}")]
        public uint D5;

        [DebuggerDisplay("{Hex.UIntToHex(D6)}")]
        public uint D6;

        [DebuggerDisplay("{Hex.UIntToHex(D7)}")]
        public uint D7;

        [DebuggerDisplay("{Hex.UIntToHex(A0)}")]
        public uint A0;

        [DebuggerDisplay("{Hex.UIntToHex(A1)}")]
        public uint A1;

        [DebuggerDisplay("{Hex.UIntToHex(A2)}")]
        public uint A2;

        [DebuggerDisplay("{Hex.UIntToHex(A3)}")]
        public uint A3;

        [DebuggerDisplay("{Hex.UIntToHex(A4)}")]
        public uint A4;

        [DebuggerDisplay("{Hex.UIntToHex(A5)}")]
        public uint A5;

        [DebuggerDisplay("{Hex.UIntToHex(A6)}")]
        public uint A6;

        /// <summary>
        /// Stack pointer = A7.
        /// </summary>
        [DebuggerDisplay("{Hex.UIntToHex(SP)}")]
        public uint SP;

        /// <summary>
        /// Program counter.
        /// </summary>
        [DebuggerDisplay("{Hex.UIntToHex(PC)}")]
        public uint PC;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="a_machine"></param>
        internal CPU680x0(Machine a_machine)
        {
            Machine = a_machine;
            Machine.OnReset += Reset;
            Memory = Machine.Memory;
        }

        /// <summary>
        /// Set processor to power-on state.
        /// </summary>
        protected virtual void Reset()
        {
            D0 = 0;
            D1 = 0;
            D2 = 0;
            D3 = 0;
            D4 = 0;
            D5 = 0;
            D6 = 0;
            D7 = 0;

            A0 = 0;
            A1 = 0;
            A2 = 0;
            A3 = 0;
            A4 = 0;
            A5 = 0;
            A6 = 0;

            SP = 0;
            PC = 0;
        }

        /// <summary>
        /// Create apriopriate CPU for machine.
        /// </summary>
        /// <param name="a_machine"></param>
        /// <returns></returns>
        internal static CPU680x0 Create(Machine a_machine)
        {
            if (a_machine.Config.CPU.Model == CPUModel.MC68000)
                return new CPU68000(a_machine);
            else if (a_machine.Config.CPU.Model == CPUModel.MC68EC020)
                return new CPU68020(a_machine);
            else
                throw new CPUInitializationException();
        }
    }
}
